home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1993…ch: Other People's Memory / ADC Developer CD (1993-03) (''Other People's Memory'')_iso / Dev.CD Mar 93.iso / Technical Documentation / Sample Code / DTS.Lib & Samples / Zippo / Window2.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-10-22  |  17.9 KB  |  515 lines  |  [TEXT/MPS ]

  1. /*
  2. ** Apple Macintosh Developer Technical Support
  3. **
  4. ** File:        Window2.c
  5. ** Written by:    Eric Soldan
  6. **
  7. ** Copyright © 1990-1992 Apple Computer, Inc.
  8. ** All rights reserved.
  9. */
  10.  
  11. /* This file contains the code for the document procedure pointers for the main Zippo
  12. ** document.  Zippo currently only supports one type of documents, type 'DUMD',
  13. ** which stands for "DUMb Document". */
  14.  
  15. /* For more information on this file, please read the read.me file "=How to write your app". */ 
  16.  
  17.  
  18.  
  19. /*****************************************************************************/
  20.  
  21.  
  22.  
  23. #include "App.h"            /* Get the application includes/typedefs, etc.    */
  24. #include "App.Common.h"        /* Get the stuff in common with rez.            */
  25. #include "App.protos.h"        /* Get the prototypes for application.            */
  26.  
  27. #ifndef __ERRORS__
  28. #include <Errors.h>
  29. #endif
  30.  
  31. #ifndef __FONTS__
  32. #include <Fonts.h>
  33. #endif
  34.  
  35. #ifndef __RESOURCES__
  36. #include <Resources.h>
  37. #endif
  38.  
  39. #ifndef __TOOLUTILS__
  40. #include <ToolUtils.h>
  41. #endif
  42.  
  43. #ifndef __UTILITIES__
  44. #include "Utilities.h"
  45. #endif
  46.  
  47.  
  48.  
  49. /*****************************************************************************/
  50.  
  51.  
  52.  
  53. Boolean            gNoDefaultDocument = false;
  54.                     /* Set to true if app should boot with no default document. */
  55.                     /* This tells DTS.Lib..framework what you want. */
  56.  
  57. short            gwAppWindow    = kwAppWindow;    /* Main window attributes. */
  58. short            gMinVersion = kMinVersion;    /* Minimum document version app can support. */
  59. short            gMaxVersion = kMaxVersion;    /* Maximum document version app can support. */
  60.                                             /* More informing DTS.Lib..framework. */
  61.  
  62. extern short        gPrintPage;                /* Non-zero means we are printing. */
  63.                                             /* DTS.Lib..framework global. */
  64.  
  65. extern RgnHandle    gCursorRgn;                /* We handle cursors here, so we need */
  66. extern CursPtr        gCursorPtr;                /* to know about these things. */
  67.                                             /* Above are DTS.Lib..framework globals. */
  68.  
  69. /* Currently Zippo doesn't ever change the cursor, so we don't actually need
  70. ** these referenced here.  However, since Zippo is supposed to be an application
  71. ** in progress, it is very likely that you will need to reference these as your
  72. ** project develops.  See DTS.Chat and DTS.Draw for examples of setting the cursor. */
  73.  
  74. /* Some cursors are pointer-based, and some cursors are resource-based.
  75. ** If a cursor is resource-based, it needs to be loaded and made to not move,
  76. ** and then gCursorPtr can be set to point to it.  This makes all cursors
  77. ** pointer-based.  Also, gCursorPtr is used by DTS.Lib..framework to
  78. ** determine if there is a current cursor.  If gCursorPtr is nil, then
  79. ** there is no current cursor, and the cursor has to be recalculated, no
  80. ** matter where the mouse is.  If gCursorPtr is not nil, then if the
  81. ** mouse position is within the cursor region gCursorRgn, the cursor is
  82. ** correct, and no recalculation is necessary.  If it is outside this region,
  83. ** then it is recalculated.  What does this all mean?  It means that if you
  84. ** want to guarantee that the cursor is recalculated next time DoWindowCursor()
  85. ** is called, set gCursorPtr to nil.
  86. **
  87. ** If you have a cursor resource, you need to:
  88. ** 1) Load the resource.
  89. ** 2) Make a fixed copy of it.
  90. ** 3) Set the cursor to it.
  91. ** 4) Set gCursorPtr to point to the fixed copy.
  92. **
  93. ** There is a function that does almost all of this, called DoSetResCursor().
  94. ** It does all but set gCursorPtr to it.  (It actually sets gCursorPtr to nil.)
  95. ** It does return a pointer to the permanent copy, so typically what you will
  96. ** want to do is the following:
  97. **     gCursorPtr = DoSetResCursor(theCursorID);
  98. **
  99. ** So why set gCursorPtr to nil as the default action?  This allows you to
  100. ** set a temporary cursor, which will be replaced when DoWindowCursor() is
  101. ** called next, or it allows you to set a cursor that maps to the cursor
  102. ** region gCursorRgn (by setting gCursorPtr to the return result). */
  103.  
  104.  
  105.  
  106. /*****************************************************************************/
  107. /*****************************************************************************/
  108.  
  109.  
  110.  
  111. /* •• You don't call this.  DTS.Lib..framework does for appropriate document type(s). •• */
  112.  
  113. /* Calculate application specific frame area (Called by DoCalcFrameRgn).
  114. ** You are passed an empty region.  You are supposed to add any custom frame
  115. ** parts that this document uses.  Typically there are no frame portions, as
  116. ** they are accounted for in other ways.  The scrollbars and grow icon will
  117. ** automatically be contributed to the calculation of the frame region.
  118. ** If you use sidebars, these are also added in automatically.  This is only
  119. ** used if the frame region is more complicated than can automatically be
  120. ** handled.  So, almost always, you will simply leave the region empty. */
  121.  
  122. #pragma segment TheDoc
  123. void    CalcFrameRgn(FileRecHndl frHndl, WindowPtr window, RgnHandle rgn)
  124. {
  125. #pragma unused (frHndl, window, rgn)
  126. }
  127.  
  128.  
  129.  
  130. /*****************************************************************************/
  131.  
  132.  
  133.  
  134. /* •• You don't call this.  DTS.Lib..framework does for appropriate document type(s). •• */
  135.  
  136. /* This is called (by DoContentClick()) when a mouse-down event occurs in the content of
  137. ** a window.  Other applications might want to call FindControl, TEClick, etc., to
  138. ** further process the click. */
  139.  
  140. #pragma segment TheDoc
  141. void    ContentClick(WindowPtr window, EventRecord *event, Boolean firstClick)
  142. {
  143. #pragma unused (firstClick)
  144.  
  145.     FileRecHndl        frHndl;
  146.     ControlHandle    ctl;
  147.     short            dblClick;
  148.  
  149.     if (IsCtlEvent(window, event, &ctl, &dblClick)) return;
  150.         /* That was easy.  Scrolling was just handled.  Other stuff would be handled
  151.         ** by IsCtlEvent, if we had other stuff to do.  We don't have any other
  152.         ** controls in the content besides the document scrollbars. */
  153.  
  154.     frHndl = (FileRecHndl)GetWRefCon(window);
  155.     if ((*frHndl)->fileState.readOnly) return;        /* Don't allow changes if read-only. */
  156.  
  157.     /* See DTS.Draw for an example of what else you might do here. */
  158. }
  159.  
  160.  
  161.  
  162. /*****************************************************************************/
  163.  
  164.  
  165.  
  166. /* •• You don't call this.  DTS.Lib..framework does for appropriate document type(s). •• */
  167.  
  168. /* DoKeyDown() is first called by the application.  Then if the key isn't a menu
  169. ** key, DoKeyDown() calls this code.  Here are the rules for this function:
  170. **
  171. ** 1) If you handle the key, return(true).  This completes the key handling.
  172. ** 2) If you don't handle the key, you return false.  However, there are two
  173. **    situations for not handling the key:
  174. **      a) You want someone else to.
  175. **      b) You want nobody else to look at the key.
  176. **    This is what the boolean passThrough is for.  If you wish the next window
  177. **    to have a look at the key, set the boolean passThrough to true.  passThrough
  178. **    is already initialized to false, which is the common case, so you only have
  179. **    to worry about setting it true.
  180. **
  181. ** If you have a window that never processes keys and always passes them through,
  182. ** just set the contentKeyProc to nil.  This will indicate to the application
  183. ** framework that all keys should be passed through this window.  DTS.Draw has
  184. ** such a window.  Its palette window doesn't accept keys.  They are passed through
  185. ** to document windows. */
  186.  
  187. #pragma segment TheDoc
  188. Boolean    ContentKey(WindowPtr window, EventRecord *event, Boolean *passThrough)
  189. {
  190. #pragma unused (passThrough)
  191.  
  192.     char        key;
  193.     FileRecHndl    frHndl;
  194.  
  195.     frHndl = (FileRecHndl)GetWRefCon(window);
  196.     if ((*frHndl)->fileState.readOnly) return(false);
  197.         /* Don't allow changes if read-only. */
  198.  
  199.     key = event->message & charCodeMask;
  200.         /* See DTS.Draw for an example of what else you might do here. */
  201.  
  202.     return(true);
  203. }
  204.  
  205.  
  206.  
  207. /*****************************************************************************/
  208.  
  209.  
  210.  
  211. /* •• You don't call this.  DTS.Lib..framework does for appropriate document type(s). •• */
  212.  
  213. /* Draw application specific content (Called by DoDrawFrame).
  214. **
  215. ** If your application has any custom frame areas, or if it uses sidebars,
  216. ** this is the function that you would put the frame drawing code.  The
  217. ** document scrollbars and grow icon drawing is handled by DTS.framework.
  218. ** Just do the sidebar and custom areas here. */
  219.  
  220. #pragma segment TheDoc
  221. void    DrawFrame(FileRecHndl frHndl, WindowPtr window)
  222. {
  223. #pragma unused (frHndl, window)
  224. }
  225.  
  226.  
  227.  
  228. /*****************************************************************************/
  229.  
  230.  
  231.  
  232. /* •• You don't call this.  DTS.Lib..framework does for appropriate document type(s). •• */
  233.  
  234. /* Frees up any application-specific memory in the document.  This is called by
  235. ** DoFreeDocument, which is called by DisposeDocument().  The application would
  236. ** call DisposeDocument(), not DoFreeDocument() or FreeDocument() directly.
  237. **
  238. ** The document may have a bunch of handles off the main handle of the document.
  239. ** This is where they are freed.  DisposeDocument calls this prior to releasing
  240. ** the ram for the main handle of the document, so release everything else
  241. ** here, or you will have a memory leak.
  242. **
  243. ** NOTE:  Calling DefaultFreeDocument() frees up all memory used by a
  244. ** hierarchical document (see TreeObj package). */
  245.  
  246. #pragma segment TheDoc
  247. OSErr    FreeDocument(FileRecHndl frHndl)
  248. {
  249.     return(DefaultFreeDocument(frHndl));
  250. }
  251.  
  252.  
  253.  
  254. /*****************************************************************************/
  255.  
  256.  
  257.  
  258. /* •• You don't call this.  DTS.Lib..framework does for appropriate document type(s). •• */
  259.  
  260. /* Any additional window disposal tasks can be handled here. */
  261.  
  262. #pragma segment TheDoc
  263. OSErr    FreeWindow(FileRecHndl frHndl, WindowPtr window)
  264. {
  265. #pragma unused (frHndl, window)
  266.  
  267.     return(noErr);
  268. }
  269.  
  270.  
  271.  
  272. /*****************************************************************************/
  273.  
  274.  
  275.  
  276. /* •• You don't call this.  DTS.Lib..framework does for appropriate document type(s). •• */
  277.  
  278. /* Image the document into the current port.
  279. **
  280. ** The only thing tricky about this function is that it needs to key off of
  281. ** the global variable gPrintPage.  gPrintPage is the current page that is
  282. ** being printed.  If gPrintPage is 0, then you are drawing to the window.
  283. **
  284. ** For when printing:
  285. **
  286. ** If gPrintPage is non-0, that is the page to be printed.  If after imaging
  287. ** the page there are no more pages, you should set gPrintPage to 0.  This
  288. ** indicates to the print loop that the end of the document has been reached.
  289. ** Even if the user indicated in the job dialog to print more pages, setting
  290. ** gPrintPage to 0 states that the last page has been printed.  This is necessary
  291. ** because the print loop can't know when printing is done.  The imaging procedure
  292. ** is the logical one to state when everything has been imaged. */
  293.  
  294. #pragma segment TheDoc
  295. OSErr    ImageDocument(FileRecHndl frHndl)
  296. {
  297. #pragma unused (frHndl)
  298.  
  299.     /* See DTS.Draw for an example of what you might do here. */
  300.  
  301.     return(noErr);
  302. }
  303.  
  304.  
  305.  
  306. /*****************************************************************************/
  307.  
  308.  
  309.  
  310. /* •• You don't call this.  DTS.Lib..framework does for appropriate document type(s). •• */
  311.  
  312. /* This function does the remaining window initialization.
  313. **
  314. ** There may be additional content initialization for the window.  At this point,
  315. ** you have a window, but it is currently invisible.  If you return noErr, then
  316. ** the window will be set to the state indicated for that window.  Why this function?
  317. ** You may wish to add controls to the content of the window.  You may have a
  318. ** TextEdit record in the content.  All of these sort of things can't be created
  319. ** until there is a window to contain them.  First a document is read in, and then
  320. ** if the document creation succeeds, a window is created for that document.
  321. ** At this point we have a document, and we are on our way to having a window.
  322. ** All that remains is any additional content initialization.  Do it, return
  323. ** noErr, and everybody's happy.  If something goes wrong here, return the error,
  324. ** and the incomplete window will be disposed of. */
  325.  
  326. #pragma segment TheDoc
  327. OSErr    InitContent(FileRecHndl frHndl, WindowPtr window)
  328. {
  329. #pragma unused (frHndl, window)
  330.  
  331.     /* See DTS.Chat for an example of what you might do here. */
  332.  
  333.     return(noErr);
  334. }
  335.  
  336.  
  337.  
  338. /*****************************************************************************/
  339.  
  340.  
  341.  
  342. /* •• You don't call this.  DTS.Lib..framework does for appropriate document type(s). •• */
  343.  
  344. /* The code below assumes that you are using the hierarchical document package.
  345. ** If you are, the entire hierarchical document is read in with just these two
  346. ** calls.  If you don't use it, you are on your own.  See DTS.Chat for an
  347. ** example of an application that uses the DTS.framework without the hierarchical
  348. ** document package. */
  349.  
  350. #pragma segment TheDoc
  351. OSErr    ReadDocument(FileRecHndl frHndl)
  352. {
  353.     OSErr    err;
  354.  
  355.     err = DefaultReadDocument(frHndl);
  356.     if (!err)
  357.         DefaultReadDocumentFixup(frHndl);
  358.  
  359.     return(err);
  360. }
  361.  
  362.  
  363.  
  364. /*****************************************************************************/
  365.  
  366.  
  367.  
  368. /* •• You don't call this.  DTS.Lib..framework does for appropriate document type(s). •• */
  369.  
  370. /* Resize application specific content (Called by ResizeWindow).
  371. **
  372. ** This gets called when a user does a zoom or window resizing operation.
  373. ** It is possible that things in the content need to be resized in conjunction
  374. ** with the resizing of the window. */
  375.  
  376. #pragma segment TheDoc
  377. void    ResizeContent(WindowPtr window, short oldh, short oldv)
  378. {
  379. #pragma unused (window, oldh, oldv)
  380.  
  381.     /* See DTS.Chat for a sample usage of this function. */
  382. }
  383.  
  384.  
  385.  
  386. /*****************************************************************************/
  387.  
  388.  
  389.  
  390. /* •• You don't call this.  DTS.Lib..framework does for appropriate document type(s). •• */
  391.  
  392. /* Scroll application specific frame (Called by DoScrollFrame).
  393. **
  394. ** Some applications may need to scroll the "frame" of the document along
  395. ** with the document contents.  This is common for applications with rulers,
  396. ** or other similar sidebar items. */
  397.  
  398. #pragma segment TheDoc
  399. void    ScrollFrame(FileRecHndl frHndl, WindowPtr window, long dh, long dv)
  400. {
  401. #pragma unused (frHndl, window, dh, dv)
  402. }
  403.  
  404.  
  405.  
  406. /*****************************************************************************/
  407.  
  408.  
  409.  
  410. /* •• You don't call this.  DTS.Lib..framework does for appropriate document type(s). •• */
  411.  
  412. /* Since the hierarchical document package isn't used by DTS.Chat,
  413. ** this function actually never gets called. */
  414.  
  415. #pragma segment TheDoc
  416. void    UndoFixup(FileRecHndl frHndl, Point contOrg, Boolean afterUndo)
  417. {
  418. #pragma unused (frHndl, contOrg, afterUndo)
  419.  
  420.     /* See DTS.Draw for an example of what you might do here. */
  421. }
  422.  
  423.  
  424.  
  425. /*****************************************************************************/
  426.  
  427.  
  428.  
  429. /* •• You don't call this.  DTS.Lib..framework does for appropriate document type(s). •• */
  430.  
  431. /* This function is where you adjust the cursor to reflect the location in the
  432. ** document or window.  You have the additional input of gCursorRgn to deal
  433. ** with.  The way that the cursor handling works is as follows:
  434. ** 1) The application calls DoWindowCursor().
  435. ** 2) DoWindowCursor() works its way through the windows/documents, front to back.
  436. **    It looks at the document's windowCursorProc and checks to see if the document
  437. **    has one.  If the document doesn't have one, then it assumes that that window
  438. **    always wants an arrow.  If the cursor is over that window, the cursor is set
  439. **    to an arrow, and we're done.  If the cursor isn't over the window, then the next
  440. **    window is tried.  If all documents don't have a windowCursorProc, then the cursor
  441. **    is set to an arrow (for the non-document area of the screen).
  442. ** 3) If a document has a windowCursorProc, then the proc is called.  The proc's
  443. **    job is as follows:
  444. **    a) If the cursor is over a position that is determined by the window, then
  445. **       the proc removes other areas from gCursorRgn.  Note that it should not
  446. **       simply set the area to what it "thinks" is the correct area.  This window
  447. **       may not be the front-most.  Other windows will have already been subtracted
  448. **       from gCursorRgn.  The resultant gCursorRgn is the correct cursor area,
  449. **       and should be passed to WaitNextEvent calls in the application (already the case
  450. **       in EventLoop.c).  Also, the cursor should be set to the correct cursor, of course.
  451. **       You should also return true, as the cursor has been determined.
  452. **    b) If the cursor is not over a position for this window, then you should
  453. **       return.  You will either pass back true or false.  If you don't wish
  454. **       windows behind this window to have a shot at cursor determination, then
  455. **       return true.  This states that the cursor is "determined".  It is, in the
  456. **       sense that no further determination will occur.  If you return false, then
  457. **       other windows get a shot at determining the cursor.
  458. **
  459. ** Setting the cursor to the correct cursor isn't as easy as you would expect.
  460. ** DTS.Lib..framework uses the global gCursorPtr as the reference to the cursor.  This is
  461. ** fine if the cursor is pointer-based, but if the cursor is resource-based, it is a bit
  462. ** more of a problem.  What you will need to do is to call DoSetResCursor() to make the
  463. ** resource cursor pointer-based.  DoSetResCursor() will set gCursorPtr to nil, and it
  464. ** also returns the pointer to the permanent copy of the cursor resource.  Just set gCursorPtr
  465. ** to the return result of DoSetResCursor(), and you will be set. */
  466.  
  467. #pragma segment TheDoc
  468. Boolean    WindowCursor(FileRecHndl frHndl, WindowPtr window, Point globalPt)
  469. {
  470. #pragma unused (frHndl, window, globalPt)
  471.  
  472.     /* For examples of applications that have non-arrow cursor regions,
  473.     ** see DTS.Chat and DTS.Draw. */
  474.  
  475.     DoSetCursor(&qd.arrow);
  476.     return(true);
  477. }
  478.  
  479.  
  480.  
  481. /*****************************************************************************/
  482.  
  483.  
  484.  
  485. /* •• You don't call this.  DTS.Lib..framework does for appropriate document type(s). •• */
  486.  
  487. /* After the DTS.Lib framework disposes of a window, it calls here.  This is
  488. ** to give the application a chance to do any additional tasks related to
  489. ** a window closing.  DTS.Chat doesn't have anything else extra to do. */
  490.  
  491. #pragma segment TheDoc
  492. void    WindowGoneFixup(WindowPtr window)
  493. {
  494. #pragma unused (window)
  495. }
  496.  
  497.  
  498.  
  499. /*****************************************************************************/
  500.  
  501.  
  502.  
  503. /* •• You don't call this.  DTS.Lib..framework does for appropriate document type(s). •• */
  504.  
  505. /* The reverse function of ReadDocument. */
  506.  
  507. #pragma segment TheDoc
  508. OSErr    WriteDocument(FileRecHndl frHndl)
  509. {
  510.     return(DefaultWriteDocument(frHndl));
  511. }
  512.  
  513.  
  514.  
  515.